const { getLiveServerUrl } = require("./../../configuration");

// Ensure ThreeJS is in global scope for the 'examples/'
global.THREE = require("three");

// Include any additional ThreeJS examples below
require("three/examples/js/controls/OrbitControls");
require("three/examples/js/shaders/CopyShader");
require("three/examples/js/postprocessing/EffectComposer");
require("three/examples/js/postprocessing/RenderPass");
require("three/examples/js/postprocessing/ShaderPass");
require("three/examples/js/postprocessing/TexturePass");
require("three/examples/js/shaders/FXAAShader");

const canvasSketch = require("canvas-sketch");
const glslify = require('glslify');

const settings = {
  animate: true, // Make the loop animated
  context: "webgl", // Get a WebGL canvas rather than 2D
};

const sketch = ({ context }) => {
  const renderer = new THREE.WebGL1Renderer({ canvas: context.canvas }); // Create a renderer
  renderer.autoClear = false;

  renderer.setClearColor("#fff", 1); // WebGL background color

  const camera = new THREE.PerspectiveCamera(50, 1, 0.01, 100); // Setup a camera
  camera.position.set(0, 0, -4);
  camera.lookAt(new THREE.Vector3());

  const controls = new THREE.OrbitControls(camera, context.canvas); // Setup camera controller
  const textureLoader = new THREE.TextureLoader();
  const bufferGeometryLoader = new THREE.BufferGeometryLoader();

  const scene = new THREE.Scene();
  const scene1 = new THREE.Scene();

  const composer = new THREE.EffectComposer(renderer);
  const pass1 = new THREE.RenderPass(scene, camera);
  composer.addPass(pass1);

  const pass2 = new THREE.RenderPass(scene1, camera);
  pass2.clearDepth = true;
  pass2.clear = false;
  composer.addPass(pass2);

  const copyPass = new THREE.ShaderPass(THREE.CopyShader);
  composer.addPass(copyPass);

  const fxaaPass = new THREE.ShaderPass(THREE.FXAAShader);

  const container = document.querySelector('canvas');
  const pixelRatio = renderer.getPixelRatio();

  fxaaPass.material.uniforms['resolution'].value.x = 1 / (container.offsetWidth * pixelRatio);
  fxaaPass.material.uniforms['resolution'].value.y = 1 / (container.offsetHeight * pixelRatio);
  composer.addPass(fxaaPass);

  const materialFront = new THREE.MeshBasicMaterial({ color: new THREE.Color('tomato'), side: THREE.FrontSide });
  const materialBack = new THREE.ShaderMaterial({
    transparent: true,
    side: THREE.BackSide,
    uniforms: {
      outline: { value: 0.05 }
    },
    vertexShader: glslify(/* glsl */`
      uniform float outline;

      void main() {
        vec3 vPosition = position + (normal * outline);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1.0);
      }
    `),
    fragmentShader:/* glsl */`
      void main() {
        gl_FragColor = vec4(vec3(0.0), 1.0);
      }
    `
  });

  bufferGeometryLoader.load(getLiveServerUrl("/assets/resources/suzanne_buffergeometry.json"), function (blenderMonkeyGeometry) {
    delete blenderMonkeyGeometry.attributes.normal;
    blenderMonkeyGeometry.computeVertexNormals(); // 通过面片法向量的平均值计算每个顶点的法向量
    const monkeyBack = new THREE.Mesh(blenderMonkeyGeometry, materialBack);
    const monkeyFront = new THREE.Mesh(blenderMonkeyGeometry, materialFront);
    scene.add(monkeyBack);
    scene1.add(monkeyFront);
  });

  // draw each frame
  return {
    // Handle resize events here
    resize({ pixelRatio, viewportWidth, viewportHeight }) {
      renderer.setPixelRatio(pixelRatio);
      renderer.setSize(viewportWidth, viewportHeight, false);
      camera.aspect = viewportWidth / viewportHeight;
      camera.updateProjectionMatrix();
    },
    // Update & render your scene here
    render({ time }) {
      controls.update();
      composer.render();
    },
    // Dispose of events & renderer for cleaner hot-reloading
    unload() {
      controls.dispose();
      renderer.dispose();
    }
  };
};

canvasSketch(sketch, settings);
